package com.neuronbit.businessflow.flow.clazz;

import com.neuronbit.javaparser.resolution.MethodUsage;
import com.neuronbit.javaparser.resolution.declarations.ResolvedMethodDeclaration;
import com.neuronbit.javaparser.resolution.declarations.ResolvedParameterDeclaration;
import com.neuronbit.javaparser.resolution.types.ResolvedType;

import java.util.Arrays;

/**
 * The type Source method info.
 */
public class SourceMethodInfo implements MethodInfo {
    private final ClassInfo classInfo;
    private final ResolvedMethodDeclaration methodDeclaration;

    /**
     * Instantiates a new Source method info.
     *
     * @param classInfo         the class info
     * @param methodDeclaration the method declaration
     */
    public SourceMethodInfo(ClassInfo classInfo, ResolvedMethodDeclaration methodDeclaration) {
        this.classInfo = classInfo;
        this.methodDeclaration = methodDeclaration;
    }

    /**
     * Instantiates a new Source method info.
     *
     * @param classInfo   the class info
     * @param methodUsage the method usage
     */
    public SourceMethodInfo(ClassInfo classInfo, MethodUsage methodUsage) {
        this.classInfo = classInfo;
        this.methodDeclaration = methodUsage.getDeclaration();
    }

    @Override
    public String getName() {
        return methodDeclaration.getName();
    }

    @Override
    public int getParameterCount() {
        return methodDeclaration.getNumberOfParams();
    }

    @Override
    public ResolvedType getReturnType() {
        return methodDeclaration.getReturnType();
    }

    @Override
    public ParameterInfo[] getParameters() {
        ParameterInfo[] parameterInfos = new ParameterInfo[methodDeclaration.getNumberOfParams()];
        for (int i = 0; i < methodDeclaration.getNumberOfParams(); i++) {
            ResolvedParameterDeclaration parameter = methodDeclaration.getParam(i);
            parameterInfos[i] = new SourceParameterInfo(parameter);
        }
        return parameterInfos;
    }

    @Override
    public ExceptionTypeInfo[] getExceptionTypes() {
        return methodDeclaration.getSpecifiedExceptions().stream().map(SourceExceptionTypeInfo::new).toArray(ExceptionTypeInfo[]::new);
    }

    @Override
    public ParameterTypeInfo[] getParameterTypes() {
        return Arrays.stream(getParameters()).map(p -> new SourceParameterTypeInfo(p.getType())).toArray(ParameterTypeInfo[]::new);
    }

    @Override
    public ClassInfo getParent() {
        return this.classInfo;
    }
}
